package com.hzit.aspect;

import com.alibaba.fastjson.JSON;
import com.hzit.annotation.RequiresPermissions;
import com.hzit.constants.TokenConstants;
import com.hzit.entity.LoginUser;
import com.hzit.exception.NotPermissionException;
import com.hzit.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Component
@Aspect
public class PreAuthorizeAspect {
	@Autowired
	private StringRedisTemplate redisTemplate;

	//1. 定义环绕通知
	@Around("@annotation(rp)")
	public Object innerAround(ProceedingJoinPoint point, RequiresPermissions rp) throws Throwable{
		//1.1 得到注解上的值
		String[] value = rp.value();
		//1.2 获到当前登录用户
		LoginUser loginUser = getLoginUser();
		//1.3 得到loginUser的权限列表
		List<String> permissions = loginUser.getPermissions();
		//1.4 判断在我们写的值中是否有权限列表permissions中的某件权限
		boolean b = matchPermission(value,permissions);
		if(!b){
			String replace = Arrays.toString(value).replace("[", "").replace("]", "");
			throw  new NotPermissionException("对" + replace + "没有权限访问！");
		}
		//1.5 执行本方法
		return point.proceed();
	}
	//2. 判断是否有权限
	private boolean matchPermission(String[] value, List<String> permissions) {
		for (String s : value) {
			 return permissions.contains(s);
		}
		return false;
	}
	//3. 得到登录用户
	private LoginUser getLoginUser() {
		//3.1 获取请求对象
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		//3.2 得到请求对象中的请求头
		String header = request.getHeader(TokenConstants.AUTHENTICATION);
		//3.3 处理请求头中前缀部分Bearer
		String token = getToken(header);
		//3.4 进行JWT解析，得到uuidToken值
		Claims claims = JwtUtil.parseToken(token);
		//3.5 再在claims中得到uuidToken
		String uuidToken  = (String) claims.get(TokenConstants.JWT_TOKEN);
		//3.6 得到redis的key
		String redisKey = getRedisKey(uuidToken);
		//3.7 通过rediskey得到loginUser字符串
		String loginUserStr = redisTemplate.opsForValue().get(redisKey);
		//3.8 转换为对象
		LoginUser loginUser = JSON.parseObject(loginUserStr, LoginUser.class);
		return loginUser;

	}
	//4. 得到token值
	private String getToken(String header) {
		if(header.startsWith("Bearer ")){
			return header.replaceAll(TokenConstants.PREFIX, "");
		}
		return null;
	}
	//5. 获取redis的key的值
	private String getRedisKey(String uuidToken) {
		return TokenConstants.REDIS_PREFIX + uuidToken;
	}
}
